package com.mlethe.library.utils.view;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.TextPaint;
import android.text.TextUtils;

import java.util.Locale;

/**
 * 圆形矢量图生成工具类
 *
 * @author Mlethe
 */
public class RoundedIconGenerator {

    private final float mIconWidthPx;
    private final float mIconHeightPx;
    private final float mCornerRadiusPx;

    private final RectF mBackgroundRect;

    private final Paint mBackgroundPaint;
    private final TextPaint mTextPaint;

    private final float mTextHeight;
    private final float mTextYOffset;

    /**
     * Constructs the generator and initializes the common members based on the display density.
     *
     * @param res             The resources used to convert sizes to px.
     * @param iconWidthDp     The width of the generated icon in dp.
     * @param iconHeightDp    The height of the generated icon in dp.
     * @param cornerRadiusDp  The radius of the corners in the icon in dp.
     * @param backgroundColor Color with which the rounded rectangle should be drawn.
     * @param textSizeDp      Size at which the text should be drawn in dp.
     */
    public RoundedIconGenerator(Resources res, int iconWidthDp, int iconHeightDp,
                                int cornerRadiusDp, int backgroundColor, int textSizeDp) {
        this(res, iconWidthDp, iconHeightDp, cornerRadiusDp, backgroundColor, textSizeDp, Color.WHITE);
    }

    /**
     * Constructs the generator and initializes the common members ignoring display density.
     *
     * @param iconWidthPx     The width of the generated icon in pixels.
     * @param iconHeightPx    The height of the generated icon in pixels.
     * @param cornerRadiusPx  The radius of the corners in the icon in pixels.
     * @param backgroundColor Color at which the rounded rectangle should be drawn.
     * @param textSizePx      Size at which the text should be drawn in pixels.
     */
    public RoundedIconGenerator(float iconWidthPx, float iconHeightPx, float cornerRadiusPx,
                                int backgroundColor, float textSizePx) {
        this(iconWidthPx, iconHeightPx, cornerRadiusPx, backgroundColor, textSizePx, Color.WHITE);
    }

    /**
     * Constructs the generator and initializes the common members based on the display density.
     *
     * @param res             The resources used to convert sizes to px.
     * @param iconWidthDp     The width of the generated icon in dp.
     * @param iconHeightDp    The height of the generated icon in dp.
     * @param cornerRadiusDp  The radius of the corners in the icon in dp.
     * @param backgroundColor Color with which the rounded rectangle should be drawn.
     * @param textSizeDp      Size at which the text should be drawn in dp.
     * @param textColor       Color at which the rounded rectangle should be drawn.
     */
    public RoundedIconGenerator(Resources res, int iconWidthDp, int iconHeightDp,
                                int cornerRadiusDp, int backgroundColor, int textSizeDp, int textColor) {
        this(res.getDisplayMetrics().density * iconWidthDp,
                res.getDisplayMetrics().density * iconHeightDp,
                res.getDisplayMetrics().density * cornerRadiusDp, backgroundColor,
                res.getDisplayMetrics().density * textSizeDp, textColor);
    }

    /**
     * Constructs the generator and initializes the common members ignoring display density.
     *
     * @param iconWidthPx     The width of the generated icon in pixels.
     * @param iconHeightPx    The height of the generated icon in pixels.
     * @param cornerRadiusPx  The radius of the corners in the icon in pixels.
     * @param backgroundColor Color at which the rounded rectangle should be drawn.
     * @param textSizePx      Size at which the text should be drawn in pixels.
     * @param textColor       Color at which the rounded rectangle should be drawn.
     */
    public RoundedIconGenerator(float iconWidthPx, float iconHeightPx, float cornerRadiusPx,
                                int backgroundColor, float textSizePx, int textColor) {
        mIconWidthPx = iconWidthPx;
        mIconHeightPx = iconHeightPx;
        mCornerRadiusPx = cornerRadiusPx;

        mBackgroundRect = new RectF(0, 0, mIconWidthPx, mIconHeightPx);

        mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBackgroundPaint.setColor(backgroundColor);

        mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(textColor);
        mTextPaint.setFakeBoldText(true);
        mTextPaint.setTextSize(textSizePx);

        Paint.FontMetrics textFontMetrics = mTextPaint.getFontMetrics();
        mTextHeight = (float) Math.ceil(textFontMetrics.bottom - textFontMetrics.top);
        mTextYOffset = -textFontMetrics.top;
    }

    /**
     * Sets the background color to use when generating icons.
     */
    public void setBackgroundColor(int color) {
        mBackgroundPaint.setColor(color);
    }

    /**
     * Sets the text color to use when generating icons.
     */
    public void setTextColor(int color) {
        mTextPaint.setColor(color);
    }

    /**
     * Generates an icon based on |text| (using the first character).
     *
     * @param text The text to render the first character of on the icon.
     * @return The generated icon.
     */
    public Bitmap generateIconForText(String text) {
        if (TextUtils.isEmpty(text)) {
            return null;
        }
        return generateIconForText(text, 1);
    }

    /**
     * Generates an icon based on |text|.
     *
     * @param text     The text to render on the icon.
     * @param numChars The maximum number of characters to return.
     * @return The generated icon.
     */
    public Bitmap generateIconForText(String text, int numChars) {
        Bitmap icon = Bitmap.createBitmap((int) mIconWidthPx, (int) mIconHeightPx, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(icon);

        canvas.drawRoundRect(mBackgroundRect, mCornerRadiusPx, mCornerRadiusPx, mBackgroundPaint);

        int length = Math.min(numChars, text.length());
        String displayText = text.substring(0, length).toUpperCase(Locale.getDefault());
        float textWidth = mTextPaint.measureText(displayText);

        canvas.drawText(
                displayText,
                (mIconWidthPx - textWidth) / 2f,
                Math.round((Math.max(mIconHeightPx, mTextHeight) - mTextHeight)
                        / 2.0f + mTextYOffset),
                mTextPaint);

        return icon;
    }

}
